/*******************************************************************************
*
*               COPYRIGHT (c) 2015-2016 Broadlink Corporation
*                         All Rights Reserved
*
* The source code contained or described herein and all documents
* related to the source code ("Material") are owned by Broadlink
* Corporation or its licensors.  Title to the Material remains
* with Broadlink Corporation or its suppliers and licensors.
*
* The Material is protected by worldwide copyright and trade secret
* laws and treaty provisions. No part of the Material may be used,
* copied, reproduced, modified, published, uploaded, posted, transmitted,
* distributed, or disclosed in any way except in accordance with the
* applicable license agreement.
*
* No license under any patent, copyright, trade secret or other
* intellectual property right is granted to or conferred upon you by
* disclosure or delivery of the Materials, either expressly, by
* implication, inducement, estoppel, except in accordance with the
* applicable license agreement.
*
* Unless otherwise agreed by Broadlink in writing, you may not remove or
* alter this notice or any other notice embedded in Materials by Broadlink
* or Broadlink's suppliers or licensors in any way.
*
*******************************************************************************/

#ifndef __DNA_JSON_H
#define __DNA_JSON_H

#ifdef __cplusplus
    extern "C" {
#endif

/** Json API Error Codes */
enum {
	DNA_E_JSON_ERRNO_BASE = 1,
	/** Json buffer overflow */
	DNA_E_JSON_OBUF,
	/** Generic json error*/
	DNA_E_JSON_FAIL,
	/** Array is empty*/
	DNA_E_JSON_EARR,
	/** Invalid json object*/
	DNA_E_JSON_INVOBJ,
	/** Invalid json document*/
	DNA_E_JSON_INVDOC,
	/** Invalid json start*/
	DNA_E_JSON_INVSTART,
	/** Json composite Member not found*/
	DNA_E_JSON_CO_MNF,
	/** Json array member not found*/
	DNA_E_JSON_ARR_MNF,
	/** Json string not found*/
	DNA_E_JSON_STR_NF,
	/** Json number not found*/
	DNA_E_JSON_NUM_NF,
	/** Json given buffer not sufficient */
	DNA_E_JSON_BUFF_TOO_SMALL,
};

#define DNA_JSON_STR_LEN  64	    /* Maximum object or member name length */
#ifdef CONFIG_HOTEL_APP
#define DNA_JSON_VAL_LEN  128	    /* Maximum value name length */
#else
#define DNA_JSON_VAL_LEN  128	    /* Maximum value name length */
#endif

/*
 * JSON object
 */
typedef struct dna_json_object {
    unsigned char dummy[16];
}dna_json_object_t;

#if defined(CONFIG_RM4_APP)
	#define DNA_JSON_VAL_MAX_CNT 900
#elif defined(CONFIG_HOTEL_APP)
	#define DNA_JSON_VAL_MAX_CNT 64
#else
    #define DNA_JSON_VAL_MAX_CNT 128
#endif

typedef struct dna_json_val_list {
	unsigned int count;
	unsigned short pos[DNA_JSON_VAL_MAX_CNT];
} dna_json_val_list_t;

typedef struct dna_json_keyval_list {
	unsigned int count;
	unsigned short key_pos[DNA_JSON_VAL_MAX_CNT];
    unsigned short val_pos[DNA_JSON_VAL_MAX_CNT];
} dna_json_keyval_list_t;

/** Initialize JSON parser
 *
 * This function initializes the JSON parser to start parsing of a json
 * string. The JSON tree may also have subtrees anchored by composite
 * objects. This function initializes the search depth to 0 (outermost
 * tree). Any JSON query function operates only at a given depth.
 * 
 * \param[out] jobj The JSON object used as a handle for other search calls
 * \param[in] buff A pointer to the string containing JSON text
 *
 */
int dna_json_object_init(dna_json_object_t * jobj, const char * buff);

/** Split KEY-VALUE of json object
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[out] buffer User buffer, used for store key-value list
 * \param[in] maxsize User buffer maxsize
 * \param[out] list Key-value list
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 * \note This API only used for standard JSON format, not support array and sub-object.
 */
int dna_json_object_split(
        dna_json_object_t * jobj,
        char * buffer, int maxsize, dna_json_keyval_list_t * list);

/** Search for a composite object
 *
 * This function searches for a composite object with a given name in the JSON
 * string. If the composite object is found the search depth is set to point to
 * the subtree anchored at this composite object. Thus any calls after this will
 * search in this subtree.
 *
 * \param[in,out] jobj The JSON object handle returned by dna_json_object_init()
 * \param[in] name The name of the composite object that should be searched
 *
 */
int dna_json_get_composite_object(dna_json_object_t * jobj, const char * name);

/** Release a composite object
 *
 * This function decrements the search depth by 1. This function is the reverse
 * of the dna_json_get_composite_object() function mentioned above. This sets the
 * JSON search depth to the last but one search depth.
 *
 *
 * \param[in,out] jobj The JSON object handler returned by dna_json_object_init()
 *
 */
int dna_json_release_composite_object(dna_json_object_t * jobj);

/** Search for a array object
 *
 * This function searches for a array object with a given name in the JSON
 * string. If the array object is found the search depth is set to point to
 * the subtree anchored at this array object. Thus any calls after this will
 * search in this subtree.
 *
 * \param[in,out] jobj The JSON object handle returned by dna_json_object_init()
 * \param[in] name The name of the array object that should be searched
 *
 */
int dna_json_get_array_object(dna_json_object_t * jobj, const char * name);

/** Release a array object
 *
 * This function decrements the search depth by 1. This function is the reverse
 * of the dna_json_get_array_object() function mentioned above. This sets the
 * JSON search depth to the last but one search depth.
 *
 *
 * \param[in,out] jobj The JSON object handler returned by dna_json_object_init()
 *
 */
int dna_json_release_array_object(dna_json_object_t * jobj);

/** Get integer value of array object
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[out] val A pointer to an integer variable in which the value will be
 * returned.
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 */
int dna_json_get_array_int(dna_json_object_t * jobj, int * val);

/** Get float value of array object
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[out] val A pointer to an float variable in which the value will be
 * returned.
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 */
int dna_json_get_array_float(dna_json_object_t * jobj, float * val);

/** Get string of array object
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[in] name The name of the array object that should be searched
 * \param[out] buffer User buffer, used for store value list
 * \param[in] maxsize User buffer maxsize
 * \param[out] list Value list
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 */
int dna_json_get_array_string(
        dna_json_object_t * jobj, const char * name,
        char * buffer, int maxsize, dna_json_val_list_t * list);

/** Get sub-object of array object
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[in] name The name of the array object that should be searched
 * \param[out] buffer User buffer, used for store value list
 * \param[in] maxsize User buffer maxsize
 * \param[out] list Value list
 *
 * \return buffer valid start pointer on Success
 * \return NULL Failure (The key was not found)
 *
 */
char * dna_json_get_array_subobj(
            dna_json_object_t * jobj, const char * name,
            char * buffer, int maxsize, dna_json_val_list_t * list);

/** Find JSON key and return string
 *
 * This function searches for a JSON key with a given name and if it is a string
 * returns the corresponding value. 
 * 
 * \note JSON Query functions operate only at the current search depth. They do
 * not recursively search subtress anchored at the current depth.
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[in] name The name of the JSON key to lookup
 * \param[out] val A pointer to buffer where the string value will be stored
 * \param[in] maxlen The length of the buffer at pointer val
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 */
int dna_json_get_val_str(dna_json_object_t * jobj, const char * name, char * val, int maxlen);

/** Find JSON key and return integer value
 *
 * This function searches for a JSON key with a given name and if it is an integer
 * returns the corresponding value. 
 * 
 * \note JSON Query functions operate only at the current search depth. They do
 * not recursively search subtress anchored at the current depth.
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[in] name The name of the JSON key to lookup
 * \param[out] val A pointer to an integer variable in which the value will be
 * returned.
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 */
int dna_json_get_val_int(dna_json_object_t * jobj, const char * name, int * val_int);

int dna_json_get_val_long_long(dna_json_object_t * jobj, const char * name, long long * val_int);

/** Find JSON key and return a floating point value
 *
 * This function searches for a JSON key with a given name and if it is a
 * floating point returns the corresponding value. 
 * 
 * \note JSON Query functions operate only at the current search depth. They do
 * not recursively search subtress anchored at the current depth.
 *
 * \param[in] jobj The JSON object handler returned by dna_json_object_init()
 * \param[in] name The name of the JSON key to lookup
 * \param[out] val A pointer to an float variable in which the value will be
 * returned.
 *
 * \return 0 Success
 * \return -1 Failure (The key was not found)
 *
 */
int dna_json_get_val_float(dna_json_object_t * jobj, const char * name, float * val);

/** Initialize the JSON generator
 *
 * This function initializes the JSON generator.
 * 
 * \param[out] jobj A pointer to the structure dna_json_object which will be used as a
 * handle for the rest of the json object operations.
 * \param[out] buff A pointer to a buffer that will be used to store the
 * generated JSON data.
 * \param[in] len The length of the buffer pointed to by buff
 */
int dna_json_str_init(dna_json_object_t * jobj, char * buff, int len);

/**  Get the JSON string length
*
*  This function used for get the JSON string valid length.
*/
int dna_json_str_len(dna_json_object_t * jobj);

/** Start a new JSON object
 *
 * This function starts a new JSON object
 */
int dna_json_start_object(dna_json_object_t * jobj);

/** Start a new composite object
 *
 * This function starts a new composite object which may have its own set of
 * key-value pairs. Any dna_json_set() calls performed after this will create
 * key-value pairs within this composite object.
 *
 * \param[in] jobj A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] name The name of the composite object that should be created.
 */
int dna_json_push_object(dna_json_object_t * jobj, const char * name);

/** Close a composite object
 *
 * This closes a composite object. Any dna_json_set() calls after this will create
 * key-value pairs at the same depth as the composite object that was closed.
 */
int dna_json_pop_object(dna_json_object_t * jobj);

/** Start a JSON array object.
 *
 * This function creates an element that has an array as its value.
 * 
 * \param[in] jobj A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] name The name of the array object
 */
int dna_json_push_array_object(dna_json_object_t * jobj, const char * name);

/** Close a JSON array object.
 *
 * This closes a previously pushed JSON object.
 */
int dna_json_pop_array_object(dna_json_object_t * jobj);

/** Close JSON object
 * 
 * This function closes a JSON object that was started earlier.
 */
int dna_json_close_object(dna_json_object_t * jobj);

int dna_json_close_array(dna_json_object_t * jobj);

/** Create a key with a string value.
 * 
 * This function adds a key-value pair to the JSON text with string as the
 * value.
 *
 * \param[in] jobj A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] name The name of the key
 * \param[in] val The string value of the key
 */
int dna_json_set_val_str(dna_json_object_t * jobj, const char * name,
			  const char * val);

/** Create a key with an integer value.
 * 
 * This function adds a key-value pair to the JSON text with an integer as the
 * value.
 *
 * \param[in] jobj A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] name The name of the key
 * \param[in] val The integer value of the key
 */
int dna_json_set_val_int(dna_json_object_t * jobj, const char *name,
			  int val);

/** Create a key with an unsigned integer value.
 *
 * This function adds a key-value pair to the JSON text with an unsigned integer
 * as the value.
 *
 * \param[in] jobj A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] name The name of the key
 * \param[in] val The unsigned integer value of the key
 */
int dna_json_set_val_uint(dna_json_object_t * jobj, const char *name,
			  unsigned int val);

/** Create a key with a float value.
 * 
 * This function adds a key-value pair to the JSON text with a float as the
 * value.
 *
 * \param[in] jobj A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] name The name of the key
 * \param[in] val The float value of the key
 */
int dna_json_set_val_float(dna_json_object_t * jobj, const char *name,
			  float val);

/** Create a string array element
 *
 * This function creates a string array element in a previously started JSON
 * array. 
 *
 * \param[in] jobj  A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] val A pointer to the string value of the array element.
 */
int dna_json_set_array_str(dna_json_object_t * jobj, const char * val);

/** Create an integer array element
 *
 * This function creates an integer array element in a previously started JSON
 * array. 
 *
 * \param[in] jobj  A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] val The integer value of the array element.
 */
int dna_json_set_array_int(dna_json_object_t * jobj, int val);

/** Create a float array element
 *
 * This function creates a float array element in a previously started JSON
 * array. 
 *
 * \param[in] jobj  A pointer to the json object handle returned by the
 * dna_json_str_init() call.
 * \param[in] val A pointer to the float value of the array element.
 */
int dna_json_set_array_float(dna_json_object_t * jobj, float val);

#ifdef __cplusplus
}
#endif

#endif

